stations.puck_fuel_table = {}
stations.puckable_groups = {'flora', 'leaves', 'flower', 'sapling', 'food'}
stations.puck_fuel_table['default:coal_lump'] = true
stations.puck_fuel_table['charcoal:charcoal'] = true

function stations.puckable(input)
   for _, v in pairs(stations.puckable_groups) do
      if minetest.get_item_group(input, v) > 0 then
         return true
      end
   end
   return false
end

function stations.puck_fuel(input)
   if stations.puck_fuel_table[input] then
      return true
   end
   return false
end

function stations.puck_formspec(cycles)
   return 'size[8,8.5]'..
      'list[current_name;src;0.5,0.5;3,3;]'..
      'list[current_name;dst;5.5,1;2,2;]'..
      'list[current_name;fuel;4,2.5;1,1;]'..
      'image[4,1.5;1,1;default_furnace_fire_bg.png^[lowpart:'..
      (cycles*10)..':default_furnace_fire_fg.png]'..
      'list[current_player;main;0,4.5;8,4;]'..
      'listring[context;dst]'..
      'listring[current_player;main]'..
      'listring[context;src]'
end

function stations.puck_can_create(pos)
   local timer = minetest.get_node_timer(pos)
   local meta = minetest.get_meta(pos)
   local cycles_count = tonumber(meta:get_string('cycles_count'))
   local inv = meta:get_inventory()
   local instack = inv:get_stack('src', 1)
   local outstack = inv:get_stack('dst', 1)
   local fuel = inv:get_stack('fuel', 1)
   local outstack_count = outstack:get_count()
   if stations.puck_count_input(pos) >= 6 and inv:room_for_item('dst', 'stations:fuel_pucks') then
      stations.puck_create_fuel(pos)
      inv:add_item('dst', 'stations:fuel_pucks')
      local cycles_count = (cycles_count - 1)
      meta:set_string('cycles_count', cycles_count)
      if cycles_count > 0 and stations.puck_count_input(pos) >= 6 then
         timer:start(10)
         meta:set_string('formspec', stations.puck_formspec(cycles_count))
      else
         local fuel_stack = fuel:get_count()
         if fuel_stack >= 1 then
            fuel:take_item(1)
            inv:set_stack('fuel', 1, fuel)
            timer:start(10)
            meta:set_string('cycles_count', 10)
            meta:set_string('formspec', stations.puck_formspec(cycles_count))
            meta:set_string('infotext', 'Making fuel pucks.')
         elseif instack:get_count() < 6 then
            meta:set_string('cycles_count', 0)
            meta:set_string('formspec', stations.puck_formspec(cycles_count))
            meta:set_string('infotext', 'Out of material/fuel.')
         else
            meta:set_string('formspec', stations.puck_formspec(0))
            meta:set_string('cycles_count', 0)
            meta:set_string('infotext', 'Fuel puck creator')
         end
      end
   else
      meta:set_string('formspec', stations.puck_formspec(0))
      meta:set_string('cycles_count', 0)
   end
end

function stations.puck_count_input(pos)
   local q = 0
   local meta = minetest.get_meta(pos)
   local inv = meta:get_inventory()
   local stacks = inv:get_list('src')
   for k in pairs(stacks) do
      q = q + inv:get_stack('src', k):get_count()
   end
   return q
end

function stations.puck_create_fuel(pos)
   local q = 6
   local meta = minetest.get_meta(pos)
   local inv = meta:get_inventory()
   local stacks = inv:get_list('src')
   for k in pairs(stacks) do
      local stack = inv:get_stack('src', k)
      if not stack:is_empty() then
         local count = stack:get_count()
         if count <= q then
            inv:set_stack('src', k, '')
            q = q - count
         else
            inv:set_stack('src', k, stack:get_name() .. ' ' .. (count - q))
            q = 0
            break
         end
      end
   end
end

minetest.register_node('stations:puck_creator', {
   description = 'Fuel puck creator',
   drawtype = 'mesh',
   mesh = 'stations_puck_stove.obj',
   tiles = {'stations_pucks.png'},
   use_texture_alpha = 'opaque',
   sounds = default.node_sound_metal_defaults(),
   paramtype2 = 'facedir',
   paramtype = 'light',
   selection_box = {
      type = 'fixed',
      fixed = {
         {-.5, -.5, -.5, .7, .5, .5},
         }
      },
   collision_box = {
      type = 'fixed',
      fixed = {
         {-.5, -.5, -.5, .5, .5, .5},
         {.7, -.5, -.4, 1.1, .0, .2},
         }
      },
   groups = {cracky =3},
   after_place_node = function(pos, placer, itemstack)
      if not epic.space_to_side(pos) then
         minetest.remove_node(pos)
         return itemstack
      end
   end,
   after_dig_node = function(pos, oldnode, oldmetadata, digger)
      epic.remove_side_node(pos, oldnode)
   end,
   on_construct = function(pos)
      local meta = minetest.get_meta(pos)
      local inv = meta:get_inventory()
      inv:set_size('main', 8*4)
      inv:set_size('src', 3*3)
      inv:set_size('dst', 2*2)
      inv:set_size('fuel', 1)
      meta:set_string('cycles_count', 0)
      meta:set_string('infotext', 'Fuel puck creator')
      meta:set_string('formspec', 'size[8,8.5]'..
         'list[current_name;src;0.5,0.5;3,3;]'..
         'list[current_name;dst;5.5,1;2,2;]'..
         'list[current_name;fuel;4,2.5;1,1;]'..
         'image[4,1.5;1,1;default_furnace_fire_bg.png]'..
         'list[current_player;main;0,4.5;8,4;]'..
         'listring[context;dst]'..
         'listring[current_player;main]'..
         'listring[context;src]')
   end,
   can_dig = function(pos)
      local meta = minetest.get_meta(pos)
      local inv = meta:get_inventory()
      if inv:is_empty('src') and inv:is_empty('dst') and inv:is_empty('fuel') then
         return true
      else
         return false
      end
   end,
   allow_metadata_inventory_put = function(pos, listname, index, stack, player)
      if listname == 'src' and stations.puckable(stack:get_name()) then
         return stack:get_count()
      elseif listname == 'fuel' and stations.puck_fuel(stack:get_name()) then
         return stack:get_count()
      else
         return 0
      end
   end,
   allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
      local inv = minetest.get_meta(pos):get_inventory()
      if from_list == to_list then
         return inv:get_stack(from_list, from_index):get_count()
      else
         return 0
      end
   end,
   allow_metadata_inventory_take = function(pos, listname, index, stack, player)
      return stack:get_count()
   end,
   on_metadata_inventory_put = function(pos, listname, index, stack, player)
      local timer = minetest.get_node_timer(pos)
      local meta = minetest.get_meta(pos)
      local inv = meta:get_inventory()
      local fuel = inv:get_stack('fuel', 1)
      local fuel_stack = fuel:get_count()
      local cycles_count = tonumber(meta:get_string('cycles_count'))
      if stations.puck_count_input(pos) >= 6 and fuel_stack >= 1 then
         if cycles_count == 0 then
            fuel:take_item(1)
            inv:set_stack('fuel', 1, fuel)
            timer:start(10)
            meta:set_string('cycles_count', 10)
            meta:set_string('formspec', stations.puck_formspec(10))
         end
         meta:set_string('infotext', 'Making fuel pucks.')
      end
   end,
   on_timer = stations.puck_can_create,
   on_rotate = function(pos, node)
      return false
   end,
})

minetest.register_node('stations:puck_creator_locked', {
   description = 'Fuel puck creator (locked)',
   drawtype = 'mesh',
   mesh = 'stations_puck_stove.obj',
   tiles = {'stations_pucks.png'},
   use_texture_alpha = 'opaque',
   sounds = default.node_sound_metal_defaults(),
   paramtype2 = 'facedir',
   paramtype = 'light',
   selection_box = {
      type = 'fixed',
      fixed = {
         {-.5, -.5, -.5, .7, .5, .5},
         }
      },
   collision_box = {
      type = 'fixed',
      fixed = {
         {-.5, -.5, -.5, .5, .5, .5},
         {.7, -.5, -.4, 1.1, .0, .2},
         }
      },
   groups = {cracky =3},
   on_construct = function(pos)
      local meta = minetest.get_meta(pos)
      local inv = meta:get_inventory()
      inv:set_size('main', 8*4)
      inv:set_size('src', 3*3)
      inv:set_size('dst', 2*2)
      inv:set_size('fuel', 1)
      meta:set_string('cycles_count', 0)
      meta:set_string('infotext', 'Fuel Puck Creator (locked)')
      meta:set_string('formspec', 'size[8,8.5]'..
         'list[current_name;src;0.5,0.5;3,3;]'..
         'list[current_name;dst;5.5,1;2,2;]'..
         'list[current_name;fuel;4,2.5;1,1;]'..
         'image[4,1.5;1,1;default_furnace_fire_bg.png]'..
         'list[current_player;main;0,4.5;8,4;]'..
         'listring[context;dst]'..
         'listring[current_player;main]'..
         'listring[context;src]')
   end,
   after_place_node = function(pos, placer, itemstack)
      if not epic.space_to_side(pos) then
         minetest.remove_node(pos)
         return itemstack
      else
         local meta = minetest.get_meta(pos)
         meta:set_string('owner',placer:get_player_name())
      end
   end,

   after_dig_node = function(pos, oldnode, oldmetadata, digger)
      epic.remove_side_node(pos, oldnode)
   end,
   can_dig = function(pos)
      local meta = minetest.get_meta(pos)
      local inv = meta:get_inventory()
      if inv:is_empty('src') and inv:is_empty('dst') and inv:is_empty('fuel') then
         return true
      else
         return false
      end
   end,
   allow_metadata_inventory_put = function(pos, listname, index, stack, player)
      local meta = minetest.get_meta(pos)
      local owner = meta:get_string('owner')
      local player_name = player:get_player_name()
      if player_name == owner then
         if listname == 'src' and stations.puckable(stack:get_name()) then
            return stack:get_count()
         elseif listname == 'fuel' and stations.puck_fuel(stack:get_name()) then
            return stack:get_count()
         else
            return 0
         end
      else
         return 0
      end
   end,
   allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
      local inv = minetest.get_meta(pos):get_inventory()
      if from_list == to_list then
         return inv:get_stack(from_list, from_index):get_count()
      else
         return 0
      end
   end,
   allow_metadata_inventory_take = function(pos, listname, index, stack, player)
      local meta = minetest.get_meta(pos)
      local owner = meta:get_string('owner')
      local player_name = player:get_player_name()
      if player_name == owner then
         return stack:get_count()
      else
         return 0
      end
   end,
   on_metadata_inventory_put = function(pos, listname, index, stack, player)
      local timer = minetest.get_node_timer(pos)
      local meta = minetest.get_meta(pos)
      local inv = meta:get_inventory()
      local fuel = inv:get_stack('fuel', 1)
      local fuel_stack = fuel:get_count()
      local cycles_count = tonumber(meta:get_string('cycles_count'))
      if stations.puck_count_input(pos) >= 6 and fuel_stack >= 1 then
         if cycles_count == 0 then
            fuel:take_item(1)
            inv:set_stack('fuel', 1, fuel)
            timer:start(10)
            meta:set_string('cycles_count', 10)
            meta:set_string('formspec', stations.puck_formspec(10))
         end
         meta:set_string('infotext', 'Making fuel pucks.')
      end
   end,
   on_timer = stations.puck_can_create,
   on_rotate = function(pos, node)
      return false
   end,
})
